package com.sybil.ot.servicio;

import com.sybil.ot.dao.FlujoDAO;
import com.sybil.ot.dao.SolicitudDAO;
import com.sybil.ot.dominio.Correo;
import com.sybil.ot.dominio.DetalleSolicitud;
import com.sybil.ot.dominio.Evento;
import com.sybil.ot.dominio.Flujo;
import com.sybil.ot.dominio.Paso;
import com.sybil.ot.dominio.Pedido;
import com.sybil.ot.dominio.ResponsablePaso;
import com.sybil.ot.dominio.Solicitud;
import com.sybil.ot.dominio.Usuario;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.mail.MessagingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("solicitudServicio")
@Transactional(readOnly = true)
public class SolicitudServicio {

   @Autowired
   private SolicitudDAO solicitudDAO;
   @Autowired
   private FlujoDAO flujoDAO;
   @Autowired
   private EmailService emailService;
   @Autowired
   private UsuarioServicio usuarioServicio;
   @Autowired
   private PedidoServicio pedidoServicio;

   public void guardar(Solicitud solicitud) {
      solicitudDAO.guardarSolicitud(solicitud);
   }

   public void editar(Solicitud solicitud) {
      solicitudDAO.editarSolicitud(solicitud);
   }

   @Transactional(readOnly = false)
   public void eliminarSolicitud(String claveFlujo, int numero) {
      Solicitud solicitud = solicitudDAO.obtenerSolicitud(claveFlujo, numero);
      solicitudDAO.eliminarSolicitud(solicitud);
   }

   public List<Solicitud> obtenerSolicitudes() {
      return solicitudDAO.obtenerSolicitudes();
   }

   public List<Solicitud> obtenerSolicitudes(String claveUsuario) {
      List<Solicitud> sols = solicitudDAO.obtenerSolicitudes(claveUsuario);
      return sols;
   }

   public Solicitud obtenerSolicitud(String claveFlujo, int numero) {
      return solicitudDAO.obtenerSolicitud(claveFlujo, numero);
   }

   public void aprobarSolicitud(String claveFlujo, int numeroSolicitud, String claveUsuario,
           String claveEvento, String comentarios) {
      Solicitud solicitud = null;
      solicitud = solicitudDAO.obtenerSolicitud(claveFlujo, numeroSolicitud);
      Paso pasoActual = solicitud.getPaso();
      List<Evento> eventos = pasoActual.getEventos();
      Evento eventoAejecutar = null;
      for (Evento even : eventos) {
         if (even.getLlave().getClaveEvento().equals(claveEvento)) {
            eventoAejecutar = even;
         }
      }
      int aprobadores = 1;//inicia en 1 porque cuenta el aprobador actual
      int aprobadoresForsozos = 1;//inicia en 1 porque cuenta el aprobador actual
      Paso pasoInicial = null;
      if (eventoAejecutar != null) {
         List<DetalleSolicitud> detallesDeSolicitud = solicitud.getDetalles();
         List<DetalleSolicitud> detalles = new ArrayList<DetalleSolicitud>();
         int numeroSiguienteDetalle = detallesDeSolicitud.size() + 1;
         Usuario solicitante = null;
         for (DetalleSolicitud detalle : detallesDeSolicitud) {
            if ("I".equals(detalle.getEvento().getPaso().getTipoPaso()) && detalle.getInstancia() == 1) {
               solicitante = detalle.getUsuario();
               pasoInicial = detalle.getEvento().getPaso();
            }
            if (!detalle.getEvento().equals(eventoAejecutar)) {
               detalles.add(detalle);
            }
         }

         List<ResponsablePaso> responsables = pasoActual.getResponsablesPaso();
         for (DetalleSolicitud detalle2 : detalles) { //detalles de la solicitud del paso actual
            for (ResponsablePaso responsable : responsables) {//responsables del paso actual
               if ("S".equals(responsable.getEsAprobador())) {//si el responsable dl paso es aprobador
                  if ("S".equals(responsable.getForzoso())) {
                     if (detalle2.getUsuario().getClave().equals(responsable.getUsuario().getClave())) {
                        aprobadoresForsozos++;
                     }
                  } else {
                     if (detalle2.getUsuario().getClave().equals(responsable.getUsuario().getClave())) {
                        aprobadores++;
                     }
                  }
               }
            }
         }
         Paso pasoSigue = null;
         if ("U".equals(eventoAejecutar.getTipoAprobacion())) {//aprobacion unica
            if (solicitud.getMontoFlujo() <= pasoActual.getMontoAprobacion()) {
               pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
            } else {
               pasoSigue = eventoAejecutar.getPasoSiguiente();
            }
         } else if ("N".equals(eventoAejecutar.getTipoAprobacion())) { //aprobacion numerica
            if ("S".equals(eventoAejecutar.getValidaForzosos())) {
               if (aprobadoresForsozos == eventoAejecutar.getNumeroAprobadores()) {
                  if (solicitud.getMontoFlujo() <= pasoActual.getMontoAprobacion()) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               } else {
                  pasoSigue = pasoActual;
               }
            } else {
               if (aprobadores == eventoAejecutar.getNumeroAprobadores()) {
                  if (solicitud.getMontoFlujo() <= pasoActual.getMontoAprobacion()) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               } else {
                  pasoSigue = pasoActual;
               }
            }
         } else { //todos aprueban
            if ("S".equals(eventoAejecutar.getValidaForzosos())) {
               if (aprobadoresForsozos == responsables.size()) {
                  if (solicitud.getMontoFlujo() <= pasoActual.getMontoAprobacion()) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               } else {
                  pasoSigue = pasoActual;
               }
            } else {
               if (aprobadores == responsables.size()) {
                  if (solicitud.getMontoFlujo() <= pasoActual.getMontoAprobacion()) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               } else {
                  pasoSigue = pasoActual;
               }
            }
         }
         if (pasoSigue != null) {
            solicitud.setPaso(pasoSigue);
            solicitud.setUsuarioModif(claveUsuario);
            if ("F".equals(pasoSigue.getTipoPaso())) {
               solicitud.setTerminado("S");
               String correcto = pasoSigue.getFinalCorrecto();
               Pedido pedido = solicitud.getPedido();
               if (pedido != null) {
                  pedido.setUsuarioModif(claveUsuario);
                  if ("S".equals(correcto)) {
                     pedido.setEstatus("FI");
                  } else {
                     pedido.setEstatus("AN");
                  }
                  pedidoServicio.editarEstatus(pedido);
               }
               solicitud.setFinalCorrecto(correcto);
            }
            DetalleSolicitud detalle = null;
            detalle = new DetalleSolicitud(claveFlujo, numeroSolicitud, numeroSiguienteDetalle);
            detalle.setInstancia(solicitud.getInstancia());
            detalle.setComentarios(comentarios);
            detalle.setEvento(eventoAejecutar);
            detalle.setUsuario(usuarioServicio.obtenerUsuario(claveUsuario));
            detalle.setCausa(null);
            detalle.setUsuarioCreo(claveUsuario);
            detalle.setFecha(new Date());
            if ("S".equals(pasoSigue.getEnviaAviso())) {
               if ("S".equals(solicitud.getTerminado())) {
                  detalle.setCorreos(notificar(numeroSolicitud, numeroSiguienteDetalle,
                          claveUsuario, solicitante, pasoInicial.getResponsablesPaso(), pasoSigue, solicitud.getFecha()));
               } else {
                  detalle.setCorreos(notificar(numeroSolicitud, numeroSiguienteDetalle,
                          claveUsuario, solicitante, pasoSigue.getResponsablesPaso(), pasoSigue, solicitud.getFecha()));
               }
            }
            solicitud.getDetalles().add(detalle);
         } else {
            //no continua
         }
      } else {
         //el evento no corresponde al paso
      }
      solicitudDAO.editarSolicitud(solicitud);
   }

   public Solicitud generarSolicitud(String claveFlujo, String claveUsuario,
           double montoFlujo, String comentarios) {
      //validar flujo
      Solicitud solicitud = null;
      Flujo flujo = flujoDAO.obtenerFlujo(claveFlujo);
      int numeroSolicitud;
      if (flujo != null) {
         if ("A".equals(flujo.getEstatus())) {
            List<Paso> pasos = flujo.getPasos();
            if (pasos.isEmpty()) {
               numeroSolicitud = 0;
            } else {
               Paso pasoInicial = null;
               for (Paso paso : pasos) {
                  if ("I".equals(paso.getTipoPaso())) {
                     pasoInicial = paso;
                  }
               }
               Evento evento = pasoInicial.getEventos().get(0);
               List<ResponsablePaso> responsables = pasoInicial.getResponsablesPaso();
               boolean esResponsable = false;
               for (ResponsablePaso responsable : responsables) {
                  if (claveUsuario.equals(responsable.getUsuario().getClave())) {
                     esResponsable = true;
                  }
               }
               if (esResponsable) {
                  numeroSolicitud = solicitudDAO.obtenerSecuencia(claveFlujo);
                  solicitud = new Solicitud(claveFlujo, numeroSolicitud);
                  solicitud.setPaso(evento.getPasoSiguiente());
                  solicitud.setMontoFlujo(montoFlujo);
                  solicitud.setInstancia(1);
                  solicitud.setTerminado("N");
                  solicitud.setFinalCorrecto("N");
                  solicitud.setUsuarioCreo(claveUsuario);
                  DetalleSolicitud detalle = null;
                  detalle = new DetalleSolicitud(claveFlujo, numeroSolicitud, 1);
                  detalle.setInstancia(1);
                  detalle.setComentarios(comentarios);
                  detalle.setEvento(evento);
                  detalle.setUsuario(usuarioServicio.obtenerUsuario(claveUsuario));
                  detalle.setCausa(null);
                  detalle.setUsuarioCreo(claveUsuario);
                  solicitud.setFecha(new Date());
                  detalle.setFecha(solicitud.getFecha());
                  if ("S".equals(evento.getPasoSiguiente().getEnviaAviso())) {
                     detalle.setCorreos(notificar(numeroSolicitud, 1,
                             claveUsuario, detalle.getUsuario(), evento.getPasoSiguiente().getResponsablesPaso(), evento.getPasoSiguiente(), solicitud.getFecha()));
                  }

                  List<DetalleSolicitud> detalles = new ArrayList<DetalleSolicitud>();
                  detalles.add(detalle);
                  solicitud.setDetalles(detalles);
               }
            }
         } else {
//            numeroSolicitud = 0;
         }
      }
      return solicitud;
   }

   private List<Correo> notificar(int numeroSolicitud, int numeroDetalle, String claveUsuarioCreo,
           Usuario solicitante, List<ResponsablePaso> responsablesIni, Paso pasoNotifica, Date fechaCreado) {
      List<Correo> correos = new ArrayList<Correo>();
      List<ResponsablePaso> responsables;

      Correo correo;
      int contadorCorreos = 0;
      if (pasoNotifica.getTipoPaso().equals("F")) {
         correo = new Correo(pasoNotifica.getFlujo().getClave(),
                 numeroSolicitud, numeroDetalle, ++contadorCorreos);
         correo.setUsuario(solicitante);
         correo.setUsuarioCreo(claveUsuarioCreo);

         solicitante.setEmail("canche.moises@cmoctezuma.com.mx");

         if (solicitante.getEmail() != null) {
            correo.setCorreo(solicitante.getEmail());
            try {
               String asunto = "Solicitud # " + numeroSolicitud
                       + " finalizada, Paso: " + pasoNotifica.getDescripcionCorta();
               String mensaje = generarMensajeFin(solicitante.getNombre(), pasoNotifica.getFlujo().getClave(),
                       pasoNotifica.getFlujo().getDescripcionCorta(),
                       numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                       solicitante.getNombre(), fechaCreado);
               emailService.enviarEmailHTML("Sistema Facturas OT Concretos<facturas.ot@cmoctezuma.com.mx>",
                       solicitante.getEmail(), asunto, mensaje);
               correo.setEstatus("E");
            } catch (MessagingException ex) {
               correo.setEstatus("O");
               correo.setComentarios(ex.getMessage());
            }
         } else {
            correo.setEstatus("O");
            correo.setComentarios("No tiene especificado su correo electronico.");
            correo.setCorreo("<<No especificado>>");
         }
         correos.add(correo);
         responsables = responsablesIni;
         for (ResponsablePaso responsable : responsables) {
            if ("S".equals(responsable.getRecibeCopia())) {
               correo = new Correo(pasoNotifica.getFlujo().getClave(),
                       numeroSolicitud, numeroDetalle, ++contadorCorreos);
               Usuario usuario = responsable.getUsuario();
               correo.setUsuario(usuario);
               correo.setUsuarioCreo(claveUsuarioCreo);

               usuario.setEmail("canche.moises@cmoctezuma.com.mx");

               if (usuario.getEmail() != null) {
                  correo.setCorreo(usuario.getEmail());
                  try {
                     String asunto = "Solicitud # " + numeroSolicitud
                             + ", Paso: " + pasoNotifica.getDescripcionCorta();
                     String mensaje = generarMensajeFin(usuario.getNombre(), pasoNotifica.getFlujo().getClave(),
                             pasoNotifica.getFlujo().getDescripcionCorta(),
                             numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                             solicitante.getNombre(), fechaCreado);
                     emailService.enviarEmailHTML("Sistema Facturas OT Concretos<facturas.ot@cmoctezuma.com.mx>",
                             usuario.getEmail(), asunto, mensaje);
                     correo.setEstatus("E");
                  } catch (MessagingException ex) {
                     correo.setEstatus("O");
                     correo.setComentarios(ex.getMessage());
                  }
               } else {
                  correo.setEstatus("O");
                  correo.setComentarios("No tiene especificado su correo electrónico.");
                  correo.setCorreo("<<No especificado>>");
               }
               correos.add(correo);
            }
         }
      } else {
         responsables = pasoNotifica.getResponsablesPaso();
         for (ResponsablePaso responsable : responsables) {
            correo = new Correo(pasoNotifica.getFlujo().getClave(),
                    numeroSolicitud, numeroDetalle, ++contadorCorreos);
            Usuario usuario = responsable.getUsuario();
            correo.setUsuario(usuario);
            correo.setUsuarioCreo(claveUsuarioCreo);

            usuario.setEmail("canche.moises@cmoctezuma.com.mx");

            if (usuario.getEmail() != null) {
               correo.setCorreo(usuario.getEmail());
               try {
                  String asunto = "Solicitud # " + numeroSolicitud
                          + ", Paso: " + pasoNotifica.getDescripcionCorta();
                  String mensaje = generarMensaje(usuario.getNombre(), pasoNotifica.getFlujo().getClave(), pasoNotifica.getFlujo().getDescripcionCorta(),
                          numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                          solicitante.getNombre(), fechaCreado);
                  emailService.enviarEmailHTML("Sistema Facturas OT Concretos<facturas.ot@cmoctezuma.com.mx>",
                          usuario.getEmail(), asunto, mensaje);
                  correo.setEstatus("E");
               } catch (MessagingException ex) {
                  correo.setEstatus("O");
                  correo.setComentarios(ex.getMessage());
               }
            } else {
               correo.setEstatus("O");
               correo.setComentarios("No tiene especificado su correo electrónico.");
               correo.setCorreo("<<No especificado>>");
            }
            correos.add(correo);
         }
      }
      return correos;
   }

   private String generarMensaje(String nombrePersona, String claveFlujo, String descripcionFlujo, int numeroSolictud, String paso,
           String solicitante, Date fecha) {
      java.text.SimpleDateFormat formateadorFecha = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
      String mensajeHTML = "<html><head><title>Mensaje aprobaci&oacute;n</title><style>"
              + "body { font: 13px Arial, Helvetica, sans-serif; color: #6d6d6d; background-color:#f0f0f0; }"
              + ".tbl_formulario td{padding: 3px;} .tbl_formulario th{text-align: right;} #pnl_foot{font-style: italic;font-size: 8pt;}"
              + "</style></head><body><h3>Estimado/a " + nombrePersona + "</h3>"
              + "<p>Se le informa que tiene un pedido pendiente para su revisi&oacute;n. <br/>"
              + "Los detalles son los siguientes:</p><br/>"
              + "<table class=\"tbl_formulario\"><tr><th>Flujo:</th><td>" + claveFlujo + "-" + descripcionFlujo
              + "</td><th>Solicitud N&deg;:</th><td>" + numeroSolictud + "</td></tr>"
              + "<tr><th>Paso:</th><td>" + paso + "</td><th>Solicitante:</th><td>" + solicitante + "</td></tr>"
              + "<tr><th>Creado:</th><td>" + formateadorFecha.format(fecha) + "</td><th></th><td></td></tr>"
              + "</table><p>Para su aprobaci&oacute;n y m&aacute;s detalle del mismo, ingrese a la siguiente liga:<br/>"
              + "<a href='" + emailService.getUrlPagina() + claveFlujo + "&sn=" + numeroSolictud
              + "'>Solicitud N&deg;: " + numeroSolictud + "</a></p><br/><p id=\"pnl_foot\">Este es un correo generado autom&aacute;ticamente, favor de no responderlo.</p>"
              + "</body></html>";
      return mensajeHTML;
   }

   private String generarMensajeFin(String nombrePersona, String claveFlujo, String descripcionFlujo, int numeroSolictud, String paso,
           String solicitante, Date fecha) {
      java.text.SimpleDateFormat formateadorFecha = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
      String mensajeHTML = "<html><head><title>Mensaje finalizaci&oacute;n</title><style>"
              + "body { font: 13px Arial, Helvetica, sans-serif; color: #6d6d6d; background-color:#f0f0f0; }"
              + ".tbl_formulario td{padding: 3px;} .tbl_formulario th{text-align: right;} #pnl_foot{font-style: italic;font-size: 8pt;}"
              + "</style></head><body><h3>Estimado/a " + nombrePersona + "</h3>"
              + "<p>Se le informa que la solicitud de aprobacion ha finalizado. <br/>"
              + "Los detalles son los siguientes:</p><br/>"
              + "<table class=\"tbl_formulario\"><tr><th>Flujo:</th><td>" + claveFlujo + "-" + descripcionFlujo
              + "</td><th>Solicitud N&deg;:</th><td>" + numeroSolictud + "</td></tr>"
              + "<tr><th>Paso:</th><td>" + paso + "</td><th>Solicitante:</th><td>" + solicitante + "</td></tr>"
              + "<tr><th>Creado:</th><td>" + formateadorFecha.format(fecha) + "</td><th></th><td></td></tr>"
              + "</table><p>Para m&aacute;s detalle del mismo, ingrese a la siguiente liga:<br/>"
              + "<a href='" + emailService.getUrlPagina() + claveFlujo + "&sn=" + numeroSolictud
              + "'>Solicitud N&deg;: " + numeroSolictud + "</a></p><br/><p id=\"pnl_foot\">Este es un correo generado autom&aacute;ticamente, favor de no responderlo.</p>"
              + "</body></html>";
      return mensajeHTML;
   }

   public List<Solicitud> obtenerHistorico(String claveFlujo, String fechaDesde, String fechaHasta,
           String estatus, String numeroSolicitud) {
      int numero = 0;
      final DateFormat soloFecha = new SimpleDateFormat("dd/MM/yyyy");
      Date fecha1 = null, fecha2 = null;
      try {
         fecha1 = soloFecha.parse(fechaDesde);
         fecha2 = soloFecha.parse(fechaHasta);
         long fin = fecha2.getTime();
         fin += 82800000 + 3540000 + 59000;//se se garegan 23 horas 59 min, 59 seg
         fecha2.setTime(fin);
      } catch (ParseException ex) {
         fecha1 = null;
         fecha2 = null;
      }
      try {
         numero = Integer.parseInt(numeroSolicitud);
      } catch (NumberFormatException ex) {
         numero = 0;
      }
      return solicitudDAO.obtenerHistorico(claveFlujo, fecha1, fecha2,
              estatus, numero);
   }
}
